﻿// Decompiled with JetBrains decompiler
// Type: MCM.LightInject.TypeConstructionInfoBuilder
// Assembly: MCMv5, Version=5.10.2.0, Culture=neutral, PublicKeyToken=null
// MVID: 7AB326B9-B2B4-41C2-9177-68E944071101
// Assembly location: D:\steam\steamapps\workshop\content\261550\2859238197\bin\Win64_Shipping_Client\MCMv5.dll

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;

#nullable disable
namespace MCM.LightInject
{
  [ExcludeFromCodeCoverage]
  internal class TypeConstructionInfoBuilder : IConstructionInfoBuilder
  {
    private readonly IConstructorSelector constructorSelector;
    private readonly IConstructorDependencySelector constructorDependencySelector;
    private readonly IPropertyDependencySelector propertyDependencySelector;
    private readonly Func<Type, string, Delegate> getConstructorDependencyExpression;
    private readonly Func<Type, string, Delegate> getPropertyDependencyExpression;

    public TypeConstructionInfoBuilder(
      IConstructorSelector constructorSelector,
      IConstructorDependencySelector constructorDependencySelector,
      IPropertyDependencySelector propertyDependencySelector,
      Func<Type, string, Delegate> getConstructorDependencyExpression,
      Func<Type, string, Delegate> getPropertyDependencyExpression)
    {
      this.constructorSelector = constructorSelector;
      this.constructorDependencySelector = constructorDependencySelector;
      this.propertyDependencySelector = propertyDependencySelector;
      this.getConstructorDependencyExpression = getConstructorDependencyExpression;
      this.getPropertyDependencyExpression = getPropertyDependencyExpression;
    }

    public ConstructionInfo Execute(Registration registration)
    {
      if (registration.FactoryExpression != null)
        return new ConstructionInfo()
        {
          FactoryDelegate = registration.FactoryExpression
        };
      Type implementingType = registration.ImplementingType;
      ConstructionInfo constructionInfo = new ConstructionInfo()
      {
        ImplementingType = implementingType
      };
      constructionInfo.PropertyDependencies.AddRange(this.GetPropertyDependencies(implementingType));
      constructionInfo.Constructor = this.constructorSelector.Execute(implementingType);
      constructionInfo.ConstructorDependencies.AddRange(this.GetConstructorDependencies(constructionInfo.Constructor));
      return constructionInfo;
    }

    private IEnumerable<ConstructorDependency> GetConstructorDependencies(
      ConstructorInfo constructorInfo)
    {
      ConstructorDependency[] array = this.constructorDependencySelector.Execute(constructorInfo).ToArray<ConstructorDependency>();
      foreach (ConstructorDependency constructorDependency in array)
        constructorDependency.FactoryExpression = this.getConstructorDependencyExpression(constructorDependency.ServiceType, constructorDependency.ServiceName);
      return (IEnumerable<ConstructorDependency>) array;
    }

    private IEnumerable<PropertyDependency> GetPropertyDependencies(Type implementingType)
    {
      PropertyDependency[] array = this.propertyDependencySelector.Execute(implementingType).ToArray<PropertyDependency>();
      foreach (PropertyDependency propertyDependency in array)
        propertyDependency.FactoryExpression = this.getPropertyDependencyExpression(propertyDependency.ServiceType, propertyDependency.ServiceName);
      return (IEnumerable<PropertyDependency>) array;
    }
  }
}
